package de.ludo.entities;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;

import de.ludo.gaming.PlayerType;
import de.ludo.util.GameStatus;

/**
 * This class defines the Game
 * 
 * @author L.Rother
 * 
 *         TODO entities
 * 
 */
@Entity
public class Game implements Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int gameId;

	@Enumerated(EnumType.STRING)
	private GameStatus status;

	/**
	 * The first player is always yellow
	 */
	@OneToOne(cascade = CascadeType.ALL)
	private Player playerYellow;

	/**
	 * The second player is always red
	 */
	@OneToOne(cascade = CascadeType.ALL)
	private Player playerRed;

	/**
	 * The third player is always green
	 */
	@OneToOne(cascade = CascadeType.ALL)
	private Player playerGreen;

	/**
	 * The fourth player is always blue
	 */
	@OneToOne(cascade = CascadeType.ALL)
	private Player playerBlue;

	// @Column(unique = true)
	// private int gameBoardId;
	/**
	 * The gameBoard consits of 72 fields (after init in logic-part) If a field
	 * has a character on it, the sessionId of the player is saved The player
	 * has four fields for his characters, in every field the actual index
	 * (1-72) is saved there
	 */
	@ElementCollection
	@CollectionTable(name = "Gameboard", joinColumns = @JoinColumn(name = "gameId"))
	private List<Integer> gameBoard;

	/**
	 * This is the current Player and his remaining dice attempts
	 */
	@OneToOne(cascade = CascadeType.ALL)
	private Player currentPlayer;
	private int remainingAttempts;

	private int remainingGamePositions;

	@OneToMany
	private List<LudoSession> requestingSessions;

	public Game() {
		super();
	}

	/**
	 * This Constructor sets the status to "OPENING" and the playerOne to the
	 * game-opener
	 * 
	 * @param gameId
	 * @param playerOne
	 */

	public Game(LudoSession session) {
		this.status = GameStatus.OPENING;
		this.setPlayerYellow(new Player(session, PlayerType.PLAYER_YELLOW));
		this.requestingSessions = new ArrayList<LudoSession>();
		this.gameBoard = new ArrayList<Integer>();
		this.remainingGamePositions = 3;
	}

	/**
	 * @return the id of this game
	 */
	public int getGameId() {
		return this.gameId;
	}

	public void setGameId(int gameId) {
		this.gameId = gameId;
	}

	/**
	 * @return the current status of this game
	 */
	public GameStatus getStatus() {
		return status;
	}

	public void setStatus(GameStatus status) {
		this.status = status;
	}

	public Player getPlayerYellow() {
		return playerYellow;
	}

	public void setPlayerYellow(Player playerYellow) {
		this.playerYellow = playerYellow;
	}

	public Player getPlayerGreen() {
		return playerGreen;
	}

	public void setPlayerGreen(Player playerGreen) {
		this.playerGreen = playerGreen;
		this.remainingGamePositions = 1;
	}

	public Player getPlayerRed() {
		return playerRed;
	}

	public void setPlayerRed(Player playerRed) {
		this.playerRed = playerRed;
		this.remainingGamePositions = 2;
	}

	public Player getPlayerBlue() {
		return playerBlue;
	}

	public void setPlayerBlue(Player playerBlue) {
		this.playerBlue = playerBlue;
		this.remainingGamePositions = 0;
	}

	public int getRemainingGamePositions() {
		return remainingGamePositions;
	}

	public void setRemainingGamePositions(int remainingGamePositions) {
		this.remainingGamePositions = remainingGamePositions;
	}

	public List<Integer> getGameBoard() {
		return gameBoard;
	}

	public void setGameBoard(List<Integer> gameBoard) {
		this.gameBoard = gameBoard;
	}

	public int[] getGameBoardAsIntArray() {
		int[] gameBoardIntArray = new int[gameBoard.size()];
		for (int i = 0; i < gameBoard.size(); i++) {
			gameBoardIntArray[i] = gameBoard.get(i);
		}
		return gameBoardIntArray;
	}

	public void setGameBoardAsIntArray(int[] gameBoardAsArray) {
		List<Integer> gameBoardList = new ArrayList<Integer>();
		for (int index = 0; index < gameBoardAsArray.length; index++) {
			gameBoardList.add(gameBoardAsArray[index]);
		}
		setGameBoard(gameBoardList);
	}

	public Player getCurrentPlayer() {
		return currentPlayer;
	}

	public void setCurrentPlayer(Player currentPlayer) {
		this.currentPlayer = currentPlayer;
	}

	public int getRemainingAttempts() {
		return remainingAttempts;
	}

	public void setRemainingAttempts(int remainingAttempts) {
		this.remainingAttempts = remainingAttempts;
	}

	public void addNewRequestingUserId(LudoSession session) {
		this.requestingSessions.add(session);
	}

	public void removeRequestingUserId(LudoSession session) {
		/**
		 * Is this right??
		 */
		this.requestingSessions.remove(session);
	}

	public List<LudoSession> getRequestingSessions() {
		return this.requestingSessions;
	}

	public void setRequestingSessions(List<LudoSession> requestingSessions) {
		this.requestingSessions = requestingSessions;
	}

}
